import os
import time
from multiprocessing import Process
from datetime import datetime


class JudgeEngine:

    def __init__(self):
        self.tmp_file_path = 'static\\tmp\\'

    def do_command(self, commands):
        for command in commands:
            os.system(command)

    def judge(self, code, code_type=0, homework=None):
        input_file = homework.input_file
        std_file = homework.output_file
        result = dict()
        if code_type == 0:
            code_file = self.tmp_file_path + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.py'
        elif code_type == 1:
            code_file = self.tmp_file_path + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.cpp'
        elif code_type == 2:
            code_file = self.tmp_file_path + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.java'
        else:
            result['status'] = -1
            result['info'] = 'the language not support'
            return result
        f = open(code_file, 'w')
        f.write(code)
        f.close()
        output_file = self.tmp_file_path + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.out'
        err_file = self.tmp_file_path + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.err'
        comp_file = self.tmp_file_path + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.comp'
        if code_type == 0:
            commands = ['python %s < %s > %s 2> %s' % (code_file, input_file, output_file, err_file)]
        elif code_type == 1:
            exe_file = self.tmp_file_path + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S')
            commands = list()
            commands.append('g++ -g -o %s %s -std=c++11 2> %s' % (exe_file, code_file, comp_file))
            commands.append('%s < %s > %s 2> %s' % (exe_file.replace('/', '\\'), input_file, output_file, err_file))
        else:
            commands = list()
            commands.append('copy %s %s' % (code_file, self.tmp_file_path + 'Main.java'))
            comp_val = datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.comp'
            commands.append('cd %s && javac Main.java 2> %s' % (self.tmp_file_path, comp_val))
            comp_file = self.tmp_file_path + comp_val
            output_val = datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.out'
            err_val = datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.err'
            input_file = '..\\..\\' + input_file
            commands.append('cd %s && java Main < %s > %s 2> %s' % (self.tmp_file_path, input_file, output_val, err_val))
            output_file = self.tmp_file_path + output_val
            err_file = self.tmp_file_path + err_val
        line = time.time()
        p = Process(target=self.do_command, args=(commands, ))
        p.start()
        is_tle = False
        while p.is_alive():
            if time.time() - line > 2:
                is_tle = True
                break
        if is_tle:
            p.kill()
        if code_type == 1 or code_type == 2:
            f = open(comp_file, 'r')
            a = f.readlines()
            f.close()
            if len(a) > 1:
                result['status'] = 5
                s = str()
                for st in a:
                    s += st
                result['info'] = s
                return result
        result['run_time'] = str(time.time() - line) + 's'
        result['length'] = str(len(code) * 2) + 'B'
        f = open(err_file, 'r')
        a = f.readlines()
        f.close()
        result['info'] = 'OK'
        if is_tle:
            result['status'] = 3
        elif len(a) > 1:
            result['status'] = 2
            s = str()
            for st in a:
                s += st
            result['info'] = s
        else:
            f1 = open(output_file, 'r')
            f2 = open(std_file, 'r')
            s1 = f1.readlines()
            s2 = f2.readlines()
            f1.close()
            f2.close()
            flag = True
            for i in range(len(s1)):
                if s1[i] != s2[i]:
                    flag = False
                    break
            if flag:
                result['status'] = 0
            else:
                result['status'] = 1
        f = open(output_file, 'r')
        s = str()
        for st in f.readlines():
            s += st
        result['code_output'] = s
        return result
